package com.jewaton.auth.security;

import com.jewaton.auth.dao.ResourcesDao;
import com.jewaton.auth.entity.Resources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 从数据库(存储介质)中加载资源与权限的对应关系
 */
public class CustomSecurityMetadataSource implements
		FilterInvocationSecurityMetadataSource {

    @Autowired
    private ResourcesDao resourcesDao;
	
	private HashMap<String, Collection<ConfigAttribute>> resMap = new HashMap<String, Collection<ConfigAttribute>>();
	
	public CustomSecurityMetadataSource(){
		loadResourceDefine();
	}
	
	/**
	 * 加载资源
	 */
	public void loadResourceDefine(){
        if (resMap == null) {
            resMap = new HashMap<String, Collection<ConfigAttribute>>();
            List<Resources> resources = this.resourcesDao.findAll();
            for (Resources resource : resources) {
                Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();
                // 通过资源名称来表示具体的权限
                // 调用权限判断的时候，必须以"ROLE_"开头
                ConfigAttribute configAttribute = new SecurityConfig("ROLE_" + resource.getResKey());
                configAttributes.add(configAttribute);
                resMap.put(resource.getResUrl(), configAttributes);
            }
        }
	}

	/**
	 * 根据路径获取访问权限
	 */
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		HttpServletRequest request = ( (FilterInvocation) object ).getHttpRequest();
		RequestMatcher matcher = null;
		String resUrl = null;
		for (Iterator<String> it =  resMap.keySet().iterator();it.hasNext();) {
			resUrl = it.next();
			matcher = new AntPathRequestMatcher(resUrl);
			if(null != resUrl && matcher.matches(request)){
				return resMap.get(resUrl);
			}
		}
		return null;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		Collection<ConfigAttribute> configAttrs = new ArrayList<ConfigAttribute>();
		for (Collection<ConfigAttribute> cas : resMap.values()) {
			configAttrs.addAll(cas);
		}
		return configAttrs;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

}
